/*
 * Copyright 2025 KylinSoft Co., Ltd.
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <https://www.gnu.org/licenses/>.
 */

#include "searchinputmethodmodel.h"

#include <QSet>

SearchDataModel::SearchDataModel(QObject *parent) : QAbstractListModel(parent) {}

int SearchDataModel::rowCount(const QModelIndex &parent) const
{
    if (parent.isValid())
    {
        return 0;
    }

    return filterInputMethodList_.size();
}

QVariant SearchDataModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid() || index.row() >= filterInputMethodList_.size())
        return QVariant();

    const auto &entry = filterInputMethodList_[index.row()]; // 获取列表中的条目对象
    switch (role)
    {
    case UniqueNameRole:
        return entry.uniqueName();
    case NameRole:
        return entry.name();
    case IconRole:
        return entry.icon();
    default:
        return QVariant();
    }

    return QVariant();
}

#if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
QHash<int, QByteArray> &SearchDataModel::roleNames() const
{
    return {
        {UniqueNameRole, "uniqueName"},
        {NameRole, "name"},
        {IconRole, "icon"}};
}
#endif

void SearchDataModel::addData(const FcitxQtInputMethodEntryList &allIMs, FcitxQtFullInputMethodEntryList currentIMS)
{
    beginResetModel();
    QSet<QString> currentKeys;
    for (const auto &currentEntry : currentIMS)
    {
        currentKeys.insert(currentEntry.uniqueName());
    }

    for (const auto &entry : allIMs)
    {
        if (!currentKeys.contains(entry.uniqueName()))
        {
            filterInputMethodList_.append(entry);
        }
    }
    endResetModel();
}

SearchInputMethodModel::SearchInputMethodModel(const FcitxDbusProvider *provider, const FcitxQtInputMethodEntryList &availableInputMethods, QObject *parent) : QSortFilterProxyModel(parent)
{
    setFilterCaseSensitivity(Qt::CaseInsensitive);
}

const QString SearchInputMethodModel::filterText() const
{
    return filterText_;
}

void SearchInputMethodModel::setFilterText(const QString &text)
{
    if (filterText_ == text)
    {
        return;
    }

    filterText_ = text;
    emit filterTextChanged();
    invalidateFilter();
}

bool SearchInputMethodModel::onlyShowCurrentLanguage() const
{
    return onlyShowCurrentLanguage_;
}

void SearchInputMethodModel::setOnlyShowCurrentLanguage(bool flag)
{
    if (onlyShowCurrentLanguage_ == flag)
    {
        return;
    }

    onlyShowCurrentLanguage_ = flag;
    emit onlyShowCurrentLanguageChanged();
    invalidateFilter();
}

bool SearchInputMethodModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
{
    if (filterText_.isEmpty())
    {
        return true;
    }

    const auto sourceModel = this->sourceModel();
    const auto nameIndex = sourceModel->index(source_row, 0, source_parent);
    const auto name = sourceModel->data(nameIndex, SearchDataModel::NameRole).toString();
    const auto uniqueName = sourceModel->data(nameIndex, SearchDataModel::UniqueNameRole).toString();

    return name.contains(filterText_, Qt::CaseInsensitive) ||
           uniqueName.contains(filterText_, Qt::CaseInsensitive);
}